package com.xh.common.thread.ctl;

import com.xh.common.thread.Priority;
import com.xh.common.thread.ext.executor.Command;
import com.xh.common.thread.ext.executor.LevelConfig;
import com.xh.common.thread.ext.executor.LevelExecutorService;
import com.xh.common.thread.ext.executor.LevelThreadPoolExecutor;
import com.xh.common.thread.ext.executor.ThreadPolicy;
import com.xh.common.thread.ext.limit.ExecutorFilter;
import com.xh.common.thread.ext.limit.LimitExecutorService;
import com.xh.common.thread.ext.limit.LimitThreadPoolExecutor;
import com.xh.common.thread.ext.queue.LevelBlockingQueue;
import com.xh.common.thread.ext.queue.LevelPriorityBlockingQueue;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPool {

    /**
     * 默认线程池的配置
     */
    private static final LevelConfig[] CONFIGS = new LevelConfig[2];

    static {
        int processors = Math.max(Runtime.getRuntime().availableProcessors(), 1);
        int corePoolSize = fit(processors * 2, 4, 6);
        int maxPoolSize = fit(processors * 3, 10, 16);
        CONFIGS[0] = new LevelConfig(corePoolSize, maxPoolSize, 10, TimeUnit.SECONDS, false);

        corePoolSize = (corePoolSize + 1) / 2;
        maxPoolSize = (maxPoolSize + 1) / 2;
        CONFIGS[1] = new LevelConfig(corePoolSize, maxPoolSize, 5, TimeUnit.SECONDS, true);
    }

    /**
     * 默认的线程池
     */
    private static LimitExecutorService<ThreadPolicy> sDefaultExecutor;

    /**
     * 下载的线程池
     */
    private static ExecutorService sCacheExecutor;

    private static ThreadFactory sThreadFactory = new NamedThreadFactory("common");

    private static ExecutorFilter<ThreadPolicy> sExecutorFilter = new ExecutorFilter<ThreadPolicy>() {
        @Override
        public void execute(Executor executor, Runnable command, ThreadPolicy policy) {
            LevelExecutorService service = (LevelExecutorService) executor;
            service.execute(command, policy);
        }
    };

    /**
     * 获取默认的线程池
     *
     * @return 默认的线程池
     */
    public static LimitExecutorService<ThreadPolicy> getDefaultExecutor() {
        synchronized (ThreadPool.class) {
            if (sDefaultExecutor == null) {
                // 创建level队列
                LevelBlockingQueue<Command> queue = new LevelPriorityBlockingQueue<>(CONFIGS.length);
                // 创建level线程池
                LevelExecutorService executor = new LevelThreadPoolExecutor(CONFIGS, queue, sThreadFactory);
                executor.setDefaultPolicy(Priority.NORMAL);
                // 创建limit线程池包装器
                sDefaultExecutor = new LimitThreadPoolExecutor<>(executor, sExecutorFilter);
            }
        }
        return sDefaultExecutor;
    }

    /**
     * 获取无限制的线程池，目前用于大文件下载
     *
     * @return 无限大的线程池
     */
    public static ExecutorService getCacheExecutor() {
        synchronized (ThreadPool.class) {
            if (sCacheExecutor == null) {
                sCacheExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 10 * 1000,
                        TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), sThreadFactory);
            }
        }
        return sCacheExecutor;
    }

    /**
     * 在最大值和最小值之间取一个最接近value的值。
     *
     * @param value value
     * @param min   min
     * @param max   max
     * @return return
     */
    private static int fit(int value, int min, int max) {
        value = Math.max(value, min);
        value = Math.min(value, max);
        return value;
    }
}
